
'use strict';

var async = require('async');
var validator = require('validator');

var db =  require('./database');
var batch = require('./batch');
var user = require('./user');
var utils = require('../public/src/utils');

(function (events) {
	events.log = function (data, callback) {
		callback = callback || function () {};

		async.waterfall([
			function (next) {
				db.incrObjectField('global', 'nextEid', next);
			},
			function (eid, next) {
				data.timestamp = Date.now();
				data.eid = eid;

				async.parallel([
					function (next) {
						db.sortedSetAdd('events:time', data.timestamp, eid, next);
					},
					function (next) {
						db.setObject('event:' + eid, data, next);
					}
				], next);
			}
		], function (err, result) {
			callback(err);
		});
	};

	events.getEvents = function (start, stop, callback) {
		async.waterfall([
			function (next) {
				db.getSortedSetRevRange('events:time', start, stop, next);
			},
			function (eids, next) {
				var keys = eids.map(function (eid) {
					return 'event:' + eid;
				});
				db.getObjects(keys, next);
			},
			function (eventsData, next) {
				eventsData = eventsData.filter(Boolean);
				addUserData(eventsData, 'uid', 'user', next);
			},
			function (eventsData, next) {
				addUserData(eventsData, 'targetUid', 'targetUser', next);
			},
			function (eventsData, next) {
				eventsData.forEach(function (event) {
					Object.keys(event).forEach(function (key) {
						if (typeof event[key] === 'string') {
							event[key] = validator.escape(String(event[key] || ''));
						}
					});
					var e = utils.merge(event);
					e.eid = e.uid = e.type = e.ip = e.user = undefined;
					event.jsonString = JSON.stringify(e, null, 4);
					event.timestampISO = new Date(parseInt(event.timestamp, 10)).toUTCString();
				});
				next(null, eventsData);
			}
		], callback);
	};

	function addUserData(eventsData, field, objectName, callback) {
		var uids = eventsData.map(function (event) {
			return event && event[field];
		}).filter(function (uid, index, array) {
			return uid && array.indexOf(uid) === index;
		});

		if (!uids.length) {
			return callback(null, eventsData);
		}

		async.parallel({
			isAdmin: function (next) {
				user.isAdministrator(uids, next);
			},
			userData: function (next) {
				user.getUsersFields(uids, ['username', 'userslug', 'picture'], next);
			}
		}, function (err, results) {
			if (err) {
				return callback(err);
			}

			var userData = results.userData;

			var map = {};
			userData.forEach(function (user, index) {
				user.isAdmin = results.isAdmin[index];
				map[user.uid] = user;
			});

			eventsData.forEach(function (event) {
				if (map[event[field]]) {
					event[objectName] = map[event[field]];
				}
			});
			callback(null, eventsData);
		});
	}

	events.deleteEvents = function (eids, callback) {
		callback = callback || function () {};
		async.parallel([
			function (next) {
				var keys = eids.map(function (eid) {
					return 'event:' + eid;
				});
				db.deleteAll(keys, next);
			},
			function (next) {
				db.sortedSetRemove('events:time', eids, next);
			}
		], callback);
	};

	events.deleteAll = function (callback) {
		callback = callback || function () {};

		batch.processSortedSet('events:time', function (eids, next) {
			events.deleteEvents(eids, next);
		}, {alwaysStartAt: 0}, callback);
	};


}(module.exports));
